package com.apanal.qlife.common.shiro.credentials;

import java.util.Collection;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.springframework.beans.factory.annotation.Autowired;

import com.apanal.qlife.common.constants.Constants;
import com.apanal.qlife.common.shiro.ShiroHelper;
import com.apanal.qlife.common.util.PropertieUtil;

/**
 * 凭证匹配器
 * 
 * 
 * @author shuliangxing
 * 
 * @date 2015-7-13下午6:04:12
 */
public class RetryLimitHashedCredentialsMatcher extends
		HashedCredentialsMatcher {

	private Cache<String, AtomicInteger> passwordRetryCache;

	@Autowired
	private SessionDAO sessionDAO;

	public RetryLimitHashedCredentialsMatcher(CacheManager cacheManager) {
		passwordRetryCache = cacheManager.getCache("passwordRetryCache");
	}

	@Override
	public boolean doCredentialsMatch(AuthenticationToken token,
			AuthenticationInfo info) {
		boolean matches = super.doCredentialsMatch(token, info);
		// 允许密码错误次数,0表示不限制次数登录
		int allowLoginCount = Integer.valueOf(PropertieUtil
				.getPropertie("allowLoginCount"));

		if (allowLoginCount > 0) {
			// 登录凭证
			String username = (String) token.getPrincipal();

			AtomicInteger retryCount = passwordRetryCache.get(username);
			if (retryCount == null) {
				retryCount = new AtomicInteger(0);
				passwordRetryCache.put(username, retryCount);
			}

			// retry count + 1
			if (retryCount.incrementAndGet() > allowLoginCount) {
				throw new ExcessiveAttemptsException();
			}

			if (matches) {
				// clear retry count
				passwordRetryCache.remove(username);
			}
		}

		// 标识重复登录session
		if (matches) {
			Collection<Session> sessions = sessionDAO.getActiveSessions();
			for (Session session : sessions) {
				String name = ShiroHelper.getPrincipal(session);
				if (name == null) {
					continue;
				}
				if (name.equals(info.getPrincipals().getPrimaryPrincipal())) {
					session.setAttribute(Constants.SESSION_REPEAT_LOGIN_KEY,
							true);
				}
			}
		}

		return matches;
	}
}
